package com.medicine.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.medicine.constant.MessageConstant;
import com.medicine.constant.StatusConstant;
import com.medicine.dto.GroupDTO;
import com.medicine.dto.GroupPageQueryDTO;
import com.medicine.entity.Group;
import com.medicine.entity.Medicine;
import com.medicine.entity.GroupMedicine;
import com.medicine.exception.DeletionNotAllowedException;
import com.medicine.exception.GroupEnableFailedException;
import com.medicine.mapper.MedicineMapper;
import com.medicine.mapper.GroupMedicineMapper;
import com.medicine.mapper.GroupMapper;
import com.medicine.result.PageResult;
import com.medicine.service.GroupService;
import com.medicine.vo.GroupVO;
import com.medicine.vo.MedicineItemVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 药组业务实现
 */
@Service
@Slf4j
public class GroupServiceImpl implements GroupService {

    @Autowired
    private GroupMapper groupMapper;
    @Autowired
    private GroupMedicineMapper groupMedicineMapper;
    @Autowired
    private MedicineMapper medicineMapper;

    /**
     * 新增药组，同时需要保存药组和药品的关联关系
     * @param groupDTO
     */
    @Transactional
    public void saveWithMedicine(GroupDTO groupDTO) {
        Group group = new Group();
        BeanUtils.copyProperties(groupDTO, group);

        //向药组表插入数据
        groupMapper.insert(group);

        //获取生成的药组id
        Long groupId = group.getId();

        List<GroupMedicine> groupMedicines = groupDTO.getGroupMedicines();
        groupMedicines.forEach(groupMedicine -> {
            groupMedicine.setGroupId(groupId);
        });

        //保存药组和药品的关联关系
        groupMedicineMapper.insertBatch(groupMedicines);
    }

    /**
     * 分页查询
     * @param groupPageQueryDTO
     * @return
     */
    public PageResult pageQuery(GroupPageQueryDTO groupPageQueryDTO) {
        int pageNum = groupPageQueryDTO.getPage();
        int pageSize = groupPageQueryDTO.getPageSize();

        PageHelper.startPage(pageNum, pageSize);
        Page<GroupVO> page = groupMapper.pageQuery(groupPageQueryDTO);
        return new PageResult(page.getTotal(), page.getResult());
    }

    /**
     * 批量删除药组
     * @param ids
     */
    @Transactional
    public void deleteBatch(List<Long> ids) {
        ids.forEach(id -> {
            Group group = groupMapper.getById(id);
            if(StatusConstant.ENABLE == group.getStatus()){
                //起售中的药组不能删除
                throw new DeletionNotAllowedException(MessageConstant.GROUP_ON_SALE);
            }
        });

        ids.forEach(groupId -> {
            //删除药组表中的数据
            groupMapper.deleteById(groupId);
            //删除药组药品关系表中的数据
            groupMedicineMapper.deleteByGroupId(groupId);
        });
    }

    /**
     * 根据id查询药组和药组药品关系
     *
     * @param id
     * @return
     */
    public GroupVO getByIdWithMedicine(Long id) {
        Group group = groupMapper.getById(id);
        List<GroupMedicine> groupMedicines = groupMedicineMapper.getByGroupId(id);

        GroupVO groupVO = new GroupVO();
        BeanUtils.copyProperties(group, groupVO);
        groupVO.setGroupMedicines(groupMedicines);

        return groupVO;
    }

    /**
     * 修改药组
     *
     * @param groupDTO
     */
    @Transactional
    public void update(GroupDTO groupDTO) {
        Group group = new Group();
        BeanUtils.copyProperties(groupDTO, group);

        //1、修改药组表，执行update
        groupMapper.update(group);

        //药组id
        Long groupId = groupDTO.getId();

        //2、删除药组和药品的关联关系，操作group_medicine表，执行delete
        groupMedicineMapper.deleteByGroupId(groupId);

        List<GroupMedicine> groupMedicines = groupDTO.getGroupMedicines();
        groupMedicines.forEach(groupMedicine -> {
            groupMedicine.setGroupId(groupId);
        });
        //3、重新插入药组和药品的关联关系，操作group_medicine表，执行insert
        groupMedicineMapper.insertBatch(groupMedicines);
    }

    /**
     * 药组起售、停售
     * @param status
     * @param id
     */
    public void startOrStop(Integer status, Long id) {
        //起售药组时，判断药组内是否有停售药品，有停售药品提示"药组内包含未启售药品，无法启售"
        if(status == StatusConstant.ENABLE){
            //select a.* from medicine a left join group_medicine b on a.id = b.medicine_id where b.group_id = ?
            List<Medicine> medicineList = medicineMapper.getByGroupId(id);
            if(medicineList != null && medicineList.size() > 0){
                medicineList.forEach(medicine -> {
                    if(StatusConstant.DISABLE == medicine.getStatus()){
                        throw new GroupEnableFailedException(MessageConstant.GROUP_ENABLE_FAILED);
                    }
                });
            }
        }

        Group group = Group.builder()
                .id(id)
                .status(status)
                .build();
        groupMapper.update(group);
    }

    /**
     * 条件查询
     * @param group
     * @return
     */
    public List<Group> list(Group group) {
        List<Group> list = groupMapper.list(group);
        return list;
    }

    /**
     * 根据id查询药品选项
     * @param id
     * @return
     */
    public List<MedicineItemVO> getMedicineItemById(Long id) {
        return groupMapper.getMedicineItemByGroupId(id);
    }
}
